#include <iostream>
#include "finite_state_machine.h"
using namespace std;

USE_NAMESPACE_FSM

enum EMAIL_STATE{
	STAT_START,
	STAT_HELO,
	STAT_EHLO,
	STAT_AUTH,
	STAT_MAIL,
	STAT_RCPT,
	STAT_DATA,
	STAT_ENDDATA,
	STAT_END,
	STAT_ERROR,
	_STAT_ALL
};
int ActionEnd( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	return _STAT_ALL;
}

int ActionError( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	return STAT_END;
}

int ActionStart( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , "helo")) == data_p ){
		return STAT_HELO;
	}else if( (locate = strcasestr( (char *)data_p , "ehlo")) == data_p ){
		return STAT_EHLO;
	}
	return STAT_ERROR;
}
int ActionHelo( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , "mail from")) == data_p ){
		return STAT_MAIL;
	}
	return STAT_ERROR;
}
int ActionEhlo( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , "auth")) == data_p ){
		return STAT_AUTH;
	}
	return STAT_ERROR;
}
int ActionAuth( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , "mail from")) == data_p ){
		return STAT_MAIL;
	}
	return STAT_ERROR;
}
int ActionMail( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , "rcpt to")) == data_p ){
		return STAT_RCPT;
	}
	return STAT_ERROR;
}
int ActionRcpt( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , "rcpt to")) == data_p ){
		return STAT_RCPT;
	}else if( (locate = strcasestr( (char *)data_p , "data")) == data_p ){
		return STAT_DATA;
	}
	return STAT_ERROR;
}

int ActionData( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , ".")) == data_p ){
		return STAT_ENDDATA;
	}else{
		return STAT_DATA;
	}
	return STAT_ERROR;
}
int ActionEnddata( FSMState * stat_p , void * data_p ){
	cout << __FUNCTION__<<endl;
	char * locate;
	if( (locate = strcasestr( (char *)data_p , "quit")) == data_p ){
		return STAT_END;
	}
	return STAT_ERROR;
}

int main(){
	CreateFSMState(stat_start	, STAT_START  , ActionStart   , STAT_HELO , STAT_EHLO    , STAT_ERROR , -1);
	CreateFSMState(stat_helo	, STAT_HELO   , ActionHelo    , STAT_MAIL , STAT_ERROR   , -1);
	CreateFSMState(stat_ehlo	, STAT_EHLO   , ActionEhlo    , STAT_AUTH , STAT_ERROR   , -1);
	CreateFSMState(stat_auth	, STAT_AUTH   , ActionAuth    , STAT_AUTH , STAT_MAIL    , STAT_ERROR , -1);
	CreateFSMState(stat_mail	, STAT_MAIL   , ActionMail    , STAT_RCPT , STAT_ERROR   , -1);
	CreateFSMState(stat_rcpt	, STAT_RCPT   , ActionRcpt    , STAT_RCPT , STAT_DATA    , STAT_ERROR , -1);
	CreateFSMState(stat_data	, STAT_DATA   , ActionData    , STAT_DATA , STAT_ENDDATA , STAT_ERROR , -1);
	CreateFSMState(stat_enddata	, STAT_ENDDATA, ActionEnddata , STAT_END  , -1);
	CreateFSMState(stat_error	, STAT_ERROR  , ActionError   , STAT_END  , -1);
	CreateFSMState(stat_end		, STAT_END    , ActionEnd     , -1);

	FSM * pFsm = new FSM();
	pFsm->BuildFSM( STAT_START , STAT_END , 
			stat_start , stat_helo , stat_ehlo , stat_auth , 
			stat_mail  , stat_rcpt , stat_data , stat_enddata ,
			stat_error , stat_end);

	pFsm->Trigger( (void *)"EHLO smtp.163.com" );
	pFsm->Trigger( (void *)"AUTH LOGIN" );
	pFsm->Trigger( (void *)"DATA" );
	pFsm->Trigger( (void *)"MAIL FROM:<test@163.com>" );
	pFsm->Trigger( (void *)"MAIL FROM:<test@163.com>" );
	pFsm->Trigger( (void *)"RCPT TO:<crazywill@163.com>" );
	pFsm->Trigger( (void *)"DATA" );
	pFsm->Trigger( (void *)"sdfasd" );
	pFsm->Trigger( (void *)"asdasd" );
	pFsm->Trigger( (void *)"asdasd" );
	pFsm->Trigger( (void *)"asdasdasd" );
	pFsm->Trigger( (void *)"asdasdas" );
	pFsm->Trigger( (void *)"." );
	pFsm->Trigger( (void *)"QUIT" );
	pFsm->Trigger( (void *)"." );
}

